#include <stdio.h>
#include <string.h>
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/obj_mac.h>
#include <unistd.h>
#include "ec.h"

void test_ec_01()
{
    EC_KEY *key1 = EC_KEY_new_c();
    EC_KEY *key2 = EC_KEY_new_c();

    EC_GROUP * group1 = EC_GROUP_new_c();
    EC_GROUP * group2 = EC_GROUP_new_c();

    int ret = 0;
    int nid = 0;
    int size = 0;
    int sig_len = 0;
    int i = 0;
    int crv_len = 0;

    group1 = EC_GROUP_new_by_curve_name_c(NID_sm2);
    group2 = EC_GROUP_new_by_curve_name_c(NID_sm2);

    EC_KEY_set_group_c(key1, group1);
    EC_KEY_set_group_c(key2, group2);

    EC_KEY_generate_key_c(key1);
    EC_KEY_generate_key_c(key2);

    EC_KEY_check_key_c(key1);
    EC_KEY_check_key_c(key2);

    size = ECDSA_size_c(key1);
    EC_KEY_print_c(key1);

    ECParameters_print_c(key1);
    ECParameters_print_c(key2);

    PEM_write_bio_EC_PUBKEY_c("build/ec_pub.pem", key1);
    PEM_write_bio_ECPrivateKey_c("build/ec_pri.pem", key1);
    PEM_write_bio_ECParams_c("build/ec_para.pem", group1);

    unsigned char digest[] = {0xe6, 0x65, 0xc2, 0x80, 0xcf, 0x27, 0xda, 0xcd, 0x1f, 0x1b, 0x6b, 0x05, 0x3c, 0xb3, 0x07, 0xf3, 0x2e, 0xe3, 0x2f, 0xd0, 0x0};
    unsigned char *sigbuf = sign_malloc_c(size);
    ECDSA_sign_c(0, digest, sigbuf, &size, key1);

    ret = ECDSA_verify_c(0, digest, sigbuf, size, key1);

    free(sigbuf);

    char buf[128];

    EC_POINT *pubkey1 = EC_POINT_new_c(group1);
    EC_POINT *pubkey2 = EC_KEY_get0_public_key_c(key2);

    ECDH_compute_key_c(buf, 128, pubkey2, key1);
    ECDH_compute_key_c(buf, 128, pubkey1, key2);

    EC_POINT_free_c(pubkey2);
    EC_POINT_free_c(pubkey1);
    EC_POINT_free_c(0);
}

void test_ec_02()
{
    int ret;
    char path[1024];
    unsigned char digest[] = {0xe6, 0x65, 0xc2, 0x80, 0xcf, 0x27, 0xda, 0xcd, 0x1f, 0x1b, 0x6b, 0x05, 0x3c, 0xb3, 0x07, 0xf3, 0x2e, 0xe3, 0x2f, 0xd0, 0x0};

    getcwd(path, 1024);
    strcat(path, "/build/ec_para.pem");
    EC_GROUP *para = PEM_read_bio_ECPKParameters_c(path);
    getcwd(path, 1024);
    strcat(path, "/build/ec_pri.pem");
    EC_KEY *keyPri = PEM_read_bio_ECPrivateKey_c(path);

    int buf_len = ECDSA_size_c(keyPri);

    unsigned char *sigbuf = sign_malloc_c(buf_len);
    ECDSA_sign_c(0, digest, sigbuf, &buf_len, keyPri);

    getcwd(path, 1024);
    strcat(path, "/build/ec_pub.pem");
    EC_KEY *keyPub = PEM_read_bio_EC_PUBKEY_c(path);

    ret = ECDSA_verify_c(0, digest, sigbuf, buf_len, keyPub);

    free(sigbuf);

    EC_GROUP_free_c(para);

    EC_KEY_free_c(keyPri);
    EC_KEY_free_c(keyPub);

    EC_GROUP_free_c(0);
    EC_KEY_free_c(0);
}

void test_ec_03()
{
    EC_KEY *key1 = EC_KEY_new_c();
    EC_GROUP * group1 = EC_GROUP_new_c();

    key1 = EC_KEY_new_by_curve_name_c(NID_sm2);
    EC_KEY_generate_key_c(key1);
    EC_KEY_check_key_c(key1);

    int size = ECDSA_size_c(key1);

    const BIGNUM *pri = EC_KEY_get0_private_key_c(key1);
    EC_KEY_get0_group_c(key1);

    unsigned char digest[] = {0xe6, 0x65, 0xc2, 0x80, 0xcf, 0x27, 0xda, 0xcd, 0x1f, 0x1b, 0x6b, 0x05, 0x3c, 0xb3, 0x07, 0xf3, 0x2e, 0xe3, 0x2f, 0xd0, 0x0};
    unsigned char *sigbuf = sign_malloc_c(size);
    ECDSA_sign_c(0, digest, sigbuf, &size, key1);
    int ret = ECDSA_verify_c(0, digest, sigbuf, size, key1);

}

void setup_ec_tests(void)
{
    test_ec_01();
    test_ec_02();
    test_ec_03();
}